import { Injectable, OnModuleInit, Type } from "@nestjs/common";
import { Controller } from "@nestjs/common/interfaces";
import { DiscoveryService, Reflector } from "@nestjs/core";
import { InstanceWrapper } from "@nestjs/core/injector/instance-wrapper";

@Injectable()
export class APIScannerService implements OnModuleInit {
    constructor(
        private discoveryService: DiscoveryService,
        private readonly reflector: Reflector) { }

    onModuleInit() {
        this.scanAllApis()
    }

    private scanAllApis() {
        console.info("Scanning all APIs...");
        // 1. get all controllers
        const controllers = this.discoveryService.getControllers();

        controllers.forEach((controller: InstanceWrapper<Controller>) => {
            const { metatype, instance } = controller;
            console.log("🚀 ~ APIScannerService ~ scanAllApis ~ metatype:", metatype?.name)
            if (!metatype) return;

            // 2. get controller basic path
            const controllerPath = this.reflector.get<string>("path", metatype);
            const basePath = controllerPath ? `/${controllerPath}` : "";

            // 3.get all methods in controller
            const methods = Object.getOwnPropertyNames(metatype.prototype)
                .filter((method): method is keyof typeof instance => {
                    return method !== 'constructor' && typeof (instance as any)[(method)] === 'function'
                });

            methods.forEach(methodName => {
                const methodPath = this.reflector.get<string>('path', metatype.prototype[methodName]);
                const fullPath = `${basePath}/${methodPath || ''} `.replace('//', '/');

                // get custom decorators on method
                const description = this.reflector.get<string>('api_description', metatype.prototype[methodName]);

                // print API info
                console.log(`- 路径: ${fullPath}`);
                console.log(`  描述: ${description || 'TODO'}`);
            })
        });
        console.log('==================================\n');
    }
}